#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <proc/readproc.h>
#include <sys/sysinfo.h>
#include <stdint.h>

// 将字节转换为更易读的单位（KB、MB、GB）
void print_human_size(char* target, size_t len, unsigned long bytes) {
    const char* units[] = { "B", "KB", "MB", "GB", "TB" };
    int i = 0;
    double size = (double)bytes;

    while (size >= 1024 && i < 4) {
        size /= 1024;
        i++;
    }

    snprintf(target, len, "%.2f %s", size, units[i]);
}

int main()
{
    // PROC_FILLCOM 进程名 /proc/#/cmdline 
    // PROC_FILLMEM 内存 /proc/#/statm 
    // PROC_FILLSTAT 进程状态 /proc/#/status
    PROCTAB* proc_tab = openproc(PROC_FILLMEM | PROC_FILLCOM | PROC_FILLSTAT);
    if (proc_tab == NULL) {
        perror("openproc failed");
        return EXIT_FAILURE;
    }
    proc_t proc_info;
    memset(&proc_info, 0, sizeof(proc_info));

    printf("Listing some processes:\n");
    printf("%-8s %-16s %-8s %-8s %-8s %-4s %-8s %-8s\n",
        "pid", "cmd", "utime", " stime", "time+", "nice", "rss", "vsize");


    // 读取前10个进程
    int proc_count = 10000;

    proc_t* pt_ret;
    long clk_tck = sysconf(_SC_CLK_TCK);
    double ut_time;
    double st_time;
    double start_time;
    uint32_t nice;
    char rss[32];   // 进程的常驻内存页集大小，单位4KB
    char vsize[32];
    while (proc_count > 0)
    {
        pt_ret = readproc(proc_tab, &proc_info);
        if (pt_ret == NULL) {
            break;
        }

        if (proc_info.cmdline != NULL) {
            // 进程用户态和内核态的cpu时间, 单位 jiffies（时钟节拍）
            ut_time = (double)proc_info.utime / clk_tck;
            st_time = (double)proc_info.stime / clk_tck;
            start_time = (double)proc_info.start_time / clk_tck;
            nice = proc_info.nice;
            memset(rss, 0, sizeof(rss));
            memset(vsize, 0, sizeof(vsize));

            print_human_size(rss, sizeof(rss), proc_info.rss * 4096);
            print_human_size(vsize, sizeof(vsize), proc_info.vsize);
            printf("%-8d %-16s %-8.2f %-8.2f %-8.2f %-4d %-8s %-8s\n",
                proc_info.tid, proc_info.cmd,
                ut_time, st_time, start_time,
                nice,
                rss, vsize
            );

            proc_count--;
        }
        memset(&proc_info, 0, sizeof(proc_info));

    }
    closeproc(proc_tab);
    return EXIT_SUCCESS;
}
